package com.quectel.multicamera;


import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;


import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.quectel.multicamera.utils.GUtilMain;
import com.quectel.multicamera.utils.PreviewParams;
import com.quectel.multicamera.utils.RecorderParams;
import com.quectel.multicamera.utils.VoldReceiver;
import com.quectel.qcarapi.cb.IQCarCamInStatusCB;
import com.quectel.qcarapi.helper.QCarCamInDetectHelper;
import com.quectel.qcarapi.stream.QCarAudio;
import com.quectel.qcarapi.stream.QCarCamera;
import com.quectel.qcarapi.osd.QCarOsd;
import com.quectel.qcarapi.image.QCarPicWriter;
import com.quectel.qcarapi.util.QCarLog;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.Vector;

public class MainActivity extends AppCompatActivity implements IQCarCamInStatusCB {
    private static String TAG = "MainActivity";

    public int[] isPreviw = new int[8];

    public static int CSI1_IPUTNUM = 0;
    public static int CSI2_IPUTNUM = 0;
    public static int CAMERANUM = 4;
    public static int csi1InputType = 0;
    public static int csi2InputType = 4;

    /******UI Component****/
    Button srButton = null;  //开启录像的Button
    /******UI Component****/

    /*****Record Service && Vold Receiver******/
    private VoldReceiver vReceiver;  // 广播接收器，接受SD卡插拔状态信息
    private RecordService service = null;
    private boolean isBind = false;
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            isBind = true;
            RecordService.RecordBinder myBinder = (RecordService.RecordBinder) binder;
            service = myBinder.getService();
            QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "ActivityA - onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBind = false;
            QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "ActivityA - onServiceDisconnected");
        }
    };
    /*****Record Service && Vold Receiver******/

    private boolean m_bTakePicFinshFlag = true;
    private QCarCamInDetectHelper detectInsert;

    public static int csi1phy_num = -1;
    public static int csi2phy_num = -1;

    private PreviewParams pParams = GUtilMain.getPreviewParams();
    private RecorderParams rParams = GUtilMain.getRecorderParams();
    private RecorderParams rMParams = GUtilMain.getMergeRecorderParams();

    /******Main OSD: preview stream && recoder Stream*****/
    private boolean bOsdFlag = false;
    /******Main OSD: preview stream && recoder Stream*****/

    public static int i = 0;

    private static void addGPUTask(int taskNum) {
        for (int i = 0; i < taskNum; i++) {
            new Thread() {
                float f1 = 27.177177797f;
                float f2 = 172.14038401131414f;
                float f3 = 13.1231231f;

                @Override
                public void run() {
                    while (true) {
                        float f = f1 * f2 * f3;
                    }
                }
            }.start();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //startAadasAndDms();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_main);

        srButton = (Button) findViewById(R.id.srButton);
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "预览分辨率选择" + getIntent().getIntExtra("size1", 0));
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "录像分辨率选择" + getIntent().getIntExtra("size2", 0));
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "预览个数" + pParams.getPreviewNum());
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "录像个数" + rParams.getRecorderNums());
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "预览 csi " + pParams.getCsiNum());
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "录像 csi " + rMParams.getCsiNum());

        csi1InputType = -1;
        csi2InputType = -1;
        csi1phy_num = -1;
        csi2phy_num = -1;

        boolean isonlyCSI1 = false;
        File csi0_device = new File("/dev/rn6864");
        if (!csi0_device.exists()) {
            isonlyCSI1 = true;
            QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, " only has csi1 !");
        }


        if (pParams.getPreviewNum() >= rParams.getRecorderNums()) {
            if (pParams.getPreviewNum() <= CAMERANUM) {
                CSI1_IPUTNUM = pParams.getPreviewNum();
                CSI2_IPUTNUM = 0;
            } else {
                CSI1_IPUTNUM = CAMERANUM;
                if (pParams.getPreviewNum() - CAMERANUM < CAMERANUM)
                    CSI2_IPUTNUM = pParams.getPreviewNum() - CAMERANUM;
                else
                    CSI2_IPUTNUM = CAMERANUM;
            }
        } else {
            if (rParams.getRecorderNums() <= CAMERANUM) {
                CSI1_IPUTNUM = rParams.getRecorderNums();
                CSI2_IPUTNUM = 0;
            } else {
                CSI1_IPUTNUM = CAMERANUM;
                if (rParams.getRecorderNums() - CAMERANUM < CAMERANUM)
                    CSI2_IPUTNUM = rParams.getRecorderNums() - CAMERANUM;
                else
                    CSI2_IPUTNUM = CAMERANUM;
            }
        }

        for (i = 0; i < 8; i++) {
            if (pParams.getPreviewNum() <= CAMERANUM) {
                if (i < pParams.getPreviewNum())
                    isPreviw[i] = 1;
                else
                    isPreviw[i] = 0;
            } else {
                if (i < CAMERANUM) {
                    isPreviw[i] = 1;
                } else if ((i - CAMERANUM) >= 0 && (i - CAMERANUM) < CAMERANUM && ((i - 4) < (pParams.getPreviewNum() - CAMERANUM))) {
                    isPreviw[i] = 1;
                } else {
                    isPreviw[i] = 0;
                }
            }

            QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, " recorder nums = " + rParams.getRecorderNums() + ", isPreviw[" + i + "] =" + isPreviw[i]);
        }
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "preview width " + pParams.getWidth() + " height " + pParams.getHeight());

        if (pParams.getCsiNum() == 0 || pParams.getCsiNum() == 2 || rMParams.getCsiNum() == 2 || rMParams.getCsiNum() == 3) {  //N4配置
            if (isonlyCSI1) {
                csi1phy_num = 1;
                csi1InputType = 16;
            } else {
                csi1phy_num = 0;
                csi1InputType = 0;
            }
            openInitCamera(csi1phy_num, 4, csi1InputType);
            addCameraDetect(csi1phy_num, 4);
        }

        //一些组合是被禁止的，比如pParams.getCsiNum() = 1和rMParams.getCsiNum() == 3
        if (!isonlyCSI1 && (pParams.getCsiNum() == 1 || rMParams.getCsiNum() == 1)) {
            csi2phy_num = 1;
            csi2InputType = 16;
            openInitCamera(csi2phy_num, 4, csi2InputType);
            addCameraDetect(csi2phy_num, 4);
        }

        if (!isonlyCSI1 && (pParams.getCsiNum() == 2 || rMParams.getCsiNum() == 3)) {
            csi2phy_num = 1;
            csi2InputType = 16;
            openInitCamera(csi2phy_num, 4, csi2InputType);
            addCameraDetect(csi2phy_num, 4);
        }

        detectInsert.startDetectThread(); // 启动热插拔检测线程

        //注册异常回调
        addMainOsd();
        startShow();
    }

    private void openInitCamera(int csiNum, int inputNum, int inputType) {
        int count = 0;
        QCarCamera qCarCamera = GUtilMain.getQCamera(csiNum);
        while (count < 10) {
            QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, " csiNum = " + csiNum + " inputNum = " + inputNum + " inputType = " + inputType);
            int ret = qCarCamera.cameraOpen(inputNum, inputType);
            if (ret == 0) {
                QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, " Open csi " + csiNum + " Success");
                break;
            } else {
                count++;
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                QCarLog.e(QCarLog.LOG_MODULE_APP, TAG, " Open Failed, cameraOpen csi " + csiNum + " return = " + ret);
            }
        }
        qCarCamera.registerOnErrorCB(GUtilMain.getErrorHandler());
    }

    // 初始化Camera热插拔状态检测函数
    private void addCameraDetect(int csiNum, int inputNum) {
        QCarCamInDetectHelper.InputParam inputParam = new QCarCamInDetectHelper.InputParam();
        inputParam.detectTime = 800;  // 800ms
        inputParam.inputNum = inputNum;
        inputParam.qCarCamera = GUtilMain.getQCamera(csiNum);
        detectInsert = QCarCamInDetectHelper.getInstance(this);
        detectInsert.setInputParam(inputParam);
    }

    @Override
    public void statusCB(int csi_num, int channel_num, int detectResult, boolean isInsert) {
        // 返回热插拔状态
        //       Log.e("QCarDetectCamInsert", "csi_num = "+ csi_num + ", channel_num = " + channel_num + ", isInsert = "+isInsert + " detectResult :" +detectResult);
    }

    private void addMainOsd() {
        new Thread(new Runnable() {
            Date date;
            String dateStr, dateStr2;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH时-mm分-ss秒");

            SimpleDateFormat sdf2 = new SimpleDateFormat("HH-mm-ss");
            int tIndex = -1;
            int tIndex2 = -1;
            String font_path = "/system/fonts/Song.ttf";
            int font_size = 4;
            QCarOsd qCarOsd;

            @Override
            public void run() {
                qCarOsd = new QCarOsd();
                qCarOsd.initOsd(font_path.getBytes(), font_size);
                qCarOsd.setOsdColor(72, 170, 120);

                sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
                sdf2.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));

                if (csi1phy_num >= 0) {
                    GUtilMain.getQCamera(csi1phy_num).setMainOsd(qCarOsd);
                }

                if (csi2phy_num >= 0) {
                    GUtilMain.getQCamera(csi2phy_num).setMainOsd(qCarOsd);
                }
                bOsdFlag = true;
                for (int i = 0; i < pParams.getPreviewNum(); i++) {
                    if (i < CAMERANUM) {
                        qCarOsd.setOsd(i, (i + "通道").getBytes(), -1, 640, 96);
                    } else {
                        qCarOsd.setOsd(i - CAMERANUM, ((i - CAMERANUM) + "通道").getBytes(), -1, 640, 96);
                    }
                }

                while (bOsdFlag) {
                    date = new Date();
                    dateStr = sdf.format(date);
                    dateStr2 = sdf2.format(date);
                    tIndex2 = qCarOsd.setOsd(-1, dateStr.getBytes(), tIndex2, 32, 96);

                    tIndex = qCarOsd.setOsd(-1, dateStr2.getBytes(), tIndex, 1100, 640);
                    try {
                        Thread.sleep(980); // 时间字幕刷新频率
                    } catch (InterruptedException ie) {
                        ie.printStackTrace();
                    }

                    /*if (++count > 50 && count < 100) {
                        QCarOsd.disableOsd();
                    } else if (count > 100 && count < 150) {
                        QCarOsd.enableOsd();
                    }*/

                }

                qCarOsd.deinitOsd();
            }
        }).start();
    }

    public void startCollision(View view) {
        RecoderInstance.getInstance().startCollision();
        Toast.makeText(getApplicationContext(), "Start Collision", Toast.LENGTH_SHORT).show();
    }

    public void startLockVideo(View view) {
        RecoderInstance.getInstance().startLockVideo();
        Toast.makeText(getApplicationContext(), "Start LockVideo", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    private void initView() {
        int pCsiNum = csi1phy_num;
        if (csi1phy_num < 0) {
            pCsiNum = csi2phy_num;
        }
        SurfaceViewFragment instance_1 = new SurfaceViewFragment(GUtilMain.getQCamera(pCsiNum), 0, isPreviw[0]);
        instance_1.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        SurfaceViewFragment instance_2 = new SurfaceViewFragment(GUtilMain.getQCamera(pCsiNum), 1, isPreviw[1]);
        instance_2.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        SurfaceViewFragment instance_3 = new SurfaceViewFragment(GUtilMain.getQCamera(pCsiNum), 2, isPreviw[2]);
        instance_3.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        SurfaceViewFragment instance_4 = new SurfaceViewFragment(GUtilMain.getQCamera(pCsiNum), 3, isPreviw[3]);
        instance_4.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        SurfaceViewFragment instance_5 = new SurfaceViewFragment(GUtilMain.getQCamera(csi2phy_num), 0, isPreviw[4]);
        instance_5.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        SurfaceViewFragment instance_6 = new SurfaceViewFragment(GUtilMain.getQCamera(csi2phy_num), 1, isPreviw[5]);
        instance_6.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        SurfaceViewFragment instance_7 = new SurfaceViewFragment(GUtilMain.getQCamera(csi2phy_num), 2, isPreviw[6]);
        instance_7.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        SurfaceViewFragment instance_8 = new SurfaceViewFragment(GUtilMain.getQCamera(csi2phy_num), 3, isPreviw[7]);
        instance_8.setPreviewSize(pParams.getWidth(), pParams.getHeight());

        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container1_0, instance_1, null)
                .replace(R.id.container1_1, instance_2, null)
                .replace(R.id.container1_2, instance_3, null)
                .replace(R.id.container1_3, instance_4, null)
                .replace(R.id.container2_0, instance_5, null)
                .replace(R.id.container2_1, instance_6, null)
                .replace(R.id.container2_2, instance_7, null)
                .replace(R.id.container2_3, instance_8, null)
                .setReorderingAllowed(true)
                .commit();

    }

    public void startShow() {
        initView();
    }

    public void startVideoRecoder(View view) {
        startRecordService();
        if (rParams.getRecorderNums() > 0 || rMParams.getCsiNum() > 0) {
            RecoderInstance.getInstance().initRecoder(csi1phy_num, csi2phy_num);
            RecoderInstance.getInstance().initMergeRecoder(csi1phy_num, csi2phy_num);
            RecoderInstance.getInstance().startRecorder();
            if (srButton != null) {
                srButton.setText("录像中");
                srButton.setClickable(false);
            }
        }
    }

    private void startRecordService() {
        Intent recordService = new Intent(GUtilMain.getqContext(), RecordService.class);
        startService(recordService);
        registerStopVoldReceiver();
    }

    private void stopRecordService() {
        Intent recordService = new Intent(GUtilMain.getqContext(), RecordService.class);
        stopService(recordService);

        unRegisterStopVoldReceiver();
    }

    private void closeCamera() {
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "closeCamera csi1phy_num = " + csi1phy_num + " csi2phy_num = " + csi2phy_num);
        Thread camCloseThread0 = null;
        Thread camCloseThread1 = null;

        if (csi1phy_num >= 0) {  //N4配置
            camCloseThread0 = new Thread(new Runnable() {
                @Override
                public void run() {
                    GUtilMain.getQCamera(csi1phy_num).cameraClose();  // 关闭ais_server，必须保证最后关闭
                    GUtilMain.getQCamera(csi1phy_num).release();  // 关闭ais_server，必须保证最后关闭
                    GUtilMain.removeQCamera(csi1phy_num);
                }
            });
            camCloseThread0.start();  // 关闭ais_server，必须保证最后关闭
        }

        if (csi2phy_num >= 0) {
            camCloseThread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    GUtilMain.getQCamera(csi2phy_num).cameraClose(); // 关闭ais_server，必须保证最后关闭
                    GUtilMain.getQCamera(csi2phy_num).release();  // 关闭ais_server，必须保证最后关闭
                    GUtilMain.removeQCamera(csi2phy_num);
                }
            });
            camCloseThread1.start();  // 关闭ais_server，必须保证最后关闭
        }

        try {
            if (camCloseThread0 != null) {
                camCloseThread0.join();
            }
            if (camCloseThread1 != null) {
                camCloseThread1.join();
            }
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }

    private void registerStopVoldReceiver() {
        vReceiver = new VoldReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
        filter.addAction(Intent.ACTION_MEDIA_EJECT);

        filter.addDataScheme("file"); //必须加上该条，否则无法接收命令
        GUtilMain.getqContext().registerReceiver(vReceiver, filter);

        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, " register media mounted and eject receiver");
    }

    private void unRegisterStopVoldReceiver() {
        if (vReceiver != null) {
            GUtilMain.getqContext().unregisterReceiver(vReceiver);
            vReceiver = null;
        }
    }


    static int nMirrorCount = -1;

    public void startMirrorImage(View view) {

        nMirrorCount++;
        if (nMirrorCount >= 10000)
            nMirrorCount = 0;
        for (i = 0; i < 4; i++) {
            if (csi1phy_num >= 0) {
                QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "startMirrorImage csi1phy_num = " + csi1phy_num + "i = " + i + " isMirror = " + nMirrorCount % 2); //CAMERANUM 一路CAMERA的最大个数
                GUtilMain.getQCamera(csi1phy_num).setPreviewMirror(i, nMirrorCount % 2 == 0);
                GUtilMain.getQCamera(csi1phy_num).setVideoStreamMirror(i, nMirrorCount % 2 == 0);
                GUtilMain.getQCamera(csi1phy_num).setSubStreamMirror(i, nMirrorCount % 2 == 0);
                GUtilMain.getQCamera(csi1phy_num).setMergeStreamMirror(i, nMirrorCount % 2 == 0);
            }

            if (csi2phy_num >= 0) {
                QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "startMirrorImage csi2phy_num = " + csi2phy_num + "i = " + i + " isMirror = " + nMirrorCount % 2); //CAMERANUM 一路CAMERA的最大个数
                GUtilMain.getQCamera(csi2phy_num).setPreviewMirror(i, nMirrorCount % 2 == 0);
                GUtilMain.getQCamera(csi2phy_num).setVideoStreamMirror(i, nMirrorCount % 2 == 0);
                GUtilMain.getQCamera(csi2phy_num).setSubStreamMirror(i, nMirrorCount % 2 == 0);
                GUtilMain.getQCamera(csi2phy_num).setMergeStreamMirror(i, nMirrorCount % 2 == 0);
            }
        }

        Toast.makeText(getApplicationContext(), "Start Mirror Image", Toast.LENGTH_SHORT).show();
    }

    static int nCount = -1;

    public void setAudioMute(View view) {
        Button item_bt = (Button) view;
        nCount++;
        if (nCount >= 10000)
            nCount = 0;
        if (0 == nCount % 2) {
            item_bt.setText("打开音频");
            QCarAudio.getInstance().setMute(true);
        } else {
            item_bt.setText("静音");
            QCarAudio.getInstance().setMute(false);
        }

        Toast.makeText(getApplicationContext(), "Audio Mute", Toast.LENGTH_SHORT).show();
    }

    public synchronized void startTakePic(View view) {
        if (m_bTakePicFinshFlag == false) {
            return;
        }
        m_bTakePicFinshFlag = false;
        //如果开启录像，拍录像分辨率的照片，如果没有开启录像，拍预览分辨率的照片
        int width = RecoderInstance.getInstance().getVid_Width() == 0 ? pParams.getWidth() : RecoderInstance.getInstance().getVid_Width();
        int height = RecoderInstance.getInstance().getVid_Height() == 0 ? pParams.getHeight() : RecoderInstance.getInstance().getVid_Height();
        Vector<QCarPicWriter> qCarPicWriterVector = new Vector<>();
        QCarPicWriter jpegEncoder;
        for (int i = 0; i < 4; i++) {
            if (csi1phy_num >= 0) {
                jpegEncoder = new QCarPicWriter(this, GUtilMain.getQCamera(csi1phy_num), i, width, height, -1);
                jpegEncoder.startJpegEncoderThread();
                qCarPicWriterVector.add(jpegEncoder);
            }
            if (csi2phy_num >= 0) {
                jpegEncoder = new QCarPicWriter(this, GUtilMain.getQCamera(csi2phy_num), i, width, height, -1);
                jpegEncoder.startJpegEncoderThread();
                qCarPicWriterVector.add(jpegEncoder);
            }
        }

        for (QCarPicWriter qCarPicWriter : qCarPicWriterVector) {
            qCarPicWriter.waitJpenEncorderEnd();
        }
        //连续快速点击拍照，会导致崩溃，主要是Toast显示的问题，上一个Toast没有显示完，这个一个Toast又在显示，会导致崩溃
        Toast.makeText(getApplicationContext(), "Take picture End ", Toast.LENGTH_SHORT).show();
        m_bTakePicFinshFlag = true;
    }

    @Override
    protected void onPause() {
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "onPause");
        super.onPause();
    }

    @Override
    protected void onStop() {
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "onStop");
        super.onStop();  //会执行previewFragment stop
    }

    @Override
    public void onBackPressed() {
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, " onBackPressed");
        super.onBackPressed();

        synchronized (this) {
            try {
                wait(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        detectInsert.stopDetectThread();  //关闭热插拔检测线程
        detectInsert.clearInputParam();
        bOsdFlag = false;

        RecoderInstance.getInstance().stopRecorder();

        super.onBackPressed();
    }

    @Override
    protected void onDestroy() {
        QCarLog.i(QCarLog.LOG_MODULE_APP, TAG, "onDestroy");
        super.onDestroy();
        closeCamera();
        stopRecordService();
    }

}
